package pers.cj.pdos.excel;


import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import pers.cj.pdos.constant.OrderType;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.service.*;
import pers.cj.pdos.utils.*;
import pers.cj.pdos.vo.DataMsg;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

public class ExcelGoodsListener extends AnalysisEventListener<ExcelGoods> {
    /**
     * 系统存在的数据-从数据库读取
     */
    
    private Company company;//所属公司

    private List<House> houseList;//默认仓库

    private Map<String,String> sysTypeMap;//分类 key-名称  value-id

    private Map<String,String> sysUnitMap;//单位 key-名称  value-id

    private Map<String,String> sysCodeMap;//条码 key-code  value-""

    private Map<String,String> sysNoMap;//条码 key-no  value-""

    private Map<String,String> sysNameMap;//名称 key-no  value-""
    
    private Map<String,String> sysAttrMap;//属性 key-名称  value-id
    private Map<Integer,String> sysAttrNameMap;//属性名 key-index value-id
    private String defaultTypeId;
    //---------------------------------------------------------------------------------

    /**
     * 导入失败的商品
     */
    private List<DataMsg> goodsMsgList=new ArrayList<>();

    /**
     * 需要新增的数据
     */
    private List<Type> typeList=new ArrayList<>();
    private List<Unit> unitList=new ArrayList<>();
    private List<Attr> attrList=new ArrayList<>();

    private List<Goods> goodsList=new ArrayList<>();
    private List<GoodsAttr> goodsAttrList=new ArrayList<>();
    private List<GoodsUnit> goodsUnitList=new ArrayList<>();
    private List<GoodsHouseWarn> goodsHouseWarnList=new ArrayList<>();

    private final String YYYYMMDD = DateUtils.getDate(new Date(), DateUtils.YYYYMMDD);

    IOrderRuleService orderRuleService;
    OrderRule orderRule;

    public void init(Company company){

        WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
        orderRuleService = (IOrderRuleService)context.getBean("orderRuleServiceImpl");
        IHouseService houseService = (IHouseService)context.getBean("houseServiceImpl");
        ITypeService typeService = (ITypeService)context.getBean("typeServiceImpl");

        IGoodsService goodsService = (IGoodsService)context.getBean("goodsServiceImpl");
        IGoodsUnitService goodsUnitService = (IGoodsUnitService)context.getBean("goodsUnitServiceImpl");
        IUnitService unitService = (IUnitService)context.getBean("unitServiceImpl");
        IAttrService attrService = (IAttrService)context.getBean("attrServiceImpl");
        IAttrNameService attrNameService = (IAttrNameService)context.getBean("attrNameServiceImpl");




        orderRule = orderRuleService.getByType(company.getId(), OrderType.SP.getType());

        TimeLog.getInstance().begin(getClass(),"初始化");
        this.company = company;
        //获取公司默认仓库
        houseList = houseService.list(company.getId());

        //处理商品分类
        String defaultTypeId = null;
        Map<String,String> sysTypeMap = new HashMap<>();
        for (Type type : typeService.list(company.getId())) {
            if (defaultTypeId == null){
                defaultTypeId = type.getId();
            }
            sysTypeMap.put(type.getName(),type.getId());
        }
        this.defaultTypeId = defaultTypeId;
        this.sysTypeMap = sysTypeMap;

        //处理商品编码
        Map<String,String> sysNoMap = new HashMap<>();
        Map<String,String> sysNameMap = new HashMap<>();
        for (Goods goods : goodsService.list(company.getId())) {
            sysNoMap.put(goods.getNo(), "");
            sysNameMap.put(goods.getName(), "");
        }
        this.sysNoMap = sysNoMap;
        this.sysNameMap = sysNameMap;

        //处理条形码
        Map<String,String> sysCodeMap = new HashMap<>();
        for (GoodsUnit goodsUnit : goodsUnitService.list(company.getId())) {
            sysCodeMap.put(goodsUnit.getCode(),"");
        }
        this.sysCodeMap = sysCodeMap;

        //处理单位
        Map<String,String> sysUnitMap = new HashMap<>();
        for (Unit unit : unitService.list(company.getId())){
            sysUnitMap.put(unit.getName(), unit.getId());
        }
        this.sysUnitMap = sysUnitMap;

        //处理属性
        Map<String,String> sysAttrMap = new HashMap<>();
        for (Attr attr : attrService.list(company.getId())){
            sysAttrMap.put(attr.getAttrValue(),attr.getId());
        }
        this.sysAttrMap = sysAttrMap;

        //处理属性名
        Map<Integer,String> sysAttrNameMap = new HashMap<>();
        List<AttrName> attrNames = attrNameService.list(company.getId());
        for (int i=1 ; i<=attrNames.size();i++) {
            sysAttrNameMap.put(i, attrNames.get(i-1).getId());
        }
        this.sysAttrNameMap = sysAttrNameMap;

        System.out.println("company:"+company);
        System.out.println("sysTypeMap:"+sysTypeMap);
        System.out.println("sysUnitMap:"+sysUnitMap);
        System.out.println("sysCodeMap:"+sysCodeMap);
        System.out.println("sysNoMap:"+sysNoMap);
        System.out.println("sysAttrMap:"+sysAttrMap);
        System.out.println("sysAttrNameMap:"+sysAttrNameMap);

        TimeLog.getInstance().end();
    }

    @Override
    public void invoke(ExcelGoods excelGoods, AnalysisContext analysisContext) {
        //Logger.getLogger(ExcelGoodsListener.class).info(excelGoods);
        process(excelGoods);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        orderRuleService.updateById(orderRule);
    }

    private DataMsg genGoodsMsg(ExcelGoods excelGoods,String msg) {
        Goods goods = new Goods();
        goods.setNo(Utils.isEmpty(excelGoods.getNo()) ? "未填写":excelGoods.getNo());
        goods.setName(Utils.isEmpty(excelGoods.getName()) ? "未填写":excelGoods.getName());
        DataMsg goodsMsg = new DataMsg();
        goodsMsg.setData(goods);
        goodsMsg.setMsg(msg);
        return goodsMsg;
    }

    /**
     * 导入商品资料注意事项
     * 1.“商品名称”、“商品编号”、“基本单位”、“基本条码”为必填项
     * 2.如您填写的“商品编号”或“基本条码”与系统内的重复，则舍弃
     * 3.如您填写的“商品编号”或“基本条码”与系统内的不重复，但表格内数据有重复，则会取第一条数据
     * 4.“基本单位”需为最小单位，“副单位与基本单位换算关系”需为大于0的整数，若未填写换算关系，则默认为1；
     * 5.为了保证库存准确，请将您在启用软件之前的真实库存余量及成本录入到期初库存中，系统会根据期初成本价及期初数量自动计算出期初总金额；
     * 6.序列号商品的期初信息请在系统内维护，导入时无法导入序列号商品的期初；。
     * 7.表格中的期初单价字段请填写期初成本单价，将会参与商品的成本计算,如填写的不是数字或不填写，则会初始化为0。
     * 8.“分类”一栏若未填写，则会自动默认值。
     * 9.重要!!!导入时本公司其他人员不可以新增商品。
     *
     * @param excelGoods
     */
    void process(ExcelGoods excelGoods){
        //检查操作
        if (Utils.isEmpty(excelGoods.getName())){
            Logger.getLogger(ExcelGoodsListener.class).info("商品名称为空,舍弃该条商品");
            goodsMsgList.add(genGoodsMsg(excelGoods,"商品名称为空"));
            return;
        }

        if (!Utils.isLetterDigit(excelGoods.getCode())){
            Logger.getLogger(ExcelGoodsListener.class).info("基本条码不是数字字母,舍弃该条商品");
            goodsMsgList.add(genGoodsMsg(excelGoods,"基本条码不是数字字母,请检查"));
            return;
        }

        if (Utils.isEmpty(excelGoods.getUnit())){
            Logger.getLogger(ExcelGoodsListener.class).info("基本单位为空,舍弃该条商品");
            goodsMsgList.add(genGoodsMsg(excelGoods,"基本单位为空"));
            return;
        }

        if (sysNoMap.containsKey(excelGoods.getNo())) {
            Logger.getLogger(ExcelGoodsListener.class).info("商品编号【"+excelGoods.getNo()+"】重复,舍弃该条商品");
            goodsMsgList.add(genGoodsMsg(excelGoods,"商品编号【"+excelGoods.getNo()+"】系统已存在"));
            return;
        }

        if (sysNameMap.containsKey(excelGoods.getName())) {
            Logger.getLogger(ExcelGoodsListener.class).info("商品名称重复【"+excelGoods.getName()+"】重复,舍弃该条商品");
            goodsMsgList.add(genGoodsMsg(excelGoods,"商品名称【"+excelGoods.getName()+"】系统已存在"));
            return;
        }

        if (sysCodeMap.containsKey(excelGoods.getCode())) {
            Logger.getLogger(ExcelGoodsListener.class).info("基本条码【"+excelGoods.getCode()+"】重复,舍弃该条商品");
            goodsMsgList.add(genGoodsMsg(excelGoods,"基本条码【"+excelGoods.getCode()+"】系统已存在"));
            return;
        }


        if (Utils.isEmpty(excelGoods.getType()) && Utils.isEmpty(defaultTypeId)) {
            //如果没有商品分类，且系统没有商品分类，则舍弃该商品
            Logger.getLogger(ExcelGoodsListener.class).info("未填写分类，且系统中没有分类,舍弃该条商品");
            goodsMsgList.add(genGoodsMsg(excelGoods,"未填写分类，且系统中还未设置分类"));
            return;
        }

        Goods goods = new Goods();
        DataUtil.processEntity(company,goods);
        goods.setSn(false);

        //未填写分类
        if (Utils.isEmpty(excelGoods.getType())){
            goods.setTypeId(defaultTypeId);
        } else {
            if (sysTypeMap.containsKey(excelGoods.getType())) {
                goods.setTypeId(sysTypeMap.get(excelGoods.getType()));
            } else {
                //系统中没有该分类，则需新增
                Type type = new Type();
                DataUtil.processEntity(company,type);
                type.setName(excelGoods.getType());
                typeList.add(type);
                goods.setTypeId(type.getId());
                //系统map中加入新增的type
                sysTypeMap.put(type.getName(),type.getId());
            }
        }

        if (Utils.isLetterDigit(excelGoods.getNo())) {
            goods.setNo(excelGoods.getNo());
        }else {
            //编号不是数字字母，系统生成对应的商品编号
            goods.setNo(getNo());
            System.out.println("编号不是数字字母，系统生成对应的商品编号：" + goods.getNo());
        }

        goods.setName(excelGoods.getName());
        goods.setNorms(excelGoods.getNorms());
        goods.setStatus("停用".equals(excelGoods.getStatus()) ? 2 : 1);
        goods.setRemark(excelGoods.getRemark());
        goodsList.add(goods);
        sysNoMap.put(goods.getNo(),"");
        sysNameMap.put(goods.getName(),"");


        Map<String, Object> map = new HashMap<>();
        map.put("goodsId", goods.getId());

        //-----------------------------商品库存预警
        for (House house : houseList){
            map.put("houseId", house.getId());
            GoodsHouseWarn goodsHouseWarn = new GoodsHouseWarn();
            DataUtil.processEntity(company, goodsHouseWarn,map);
            goodsHouseWarn.setMin(new BigDecimal(excelGoods.getHouseWarnMin()));
            goodsHouseWarn.setMax(new BigDecimal(excelGoods.getHouseWarnMax()));
            goodsHouseWarnList.add(goodsHouseWarn);
        }

        map.remove("houseId");
        //-----------------------------属性
        for (int i=1;i<6;i++){
            setAttr(i,excelGoods,map);
        }


        //-----------------------------单位map用于存储本商品已经添加单位
        Map<String,String> unitMap = new HashMap<>();

        for (int i=0;i<4;i++) {
            String unitName;
            String times;
            String code;
            String retailPrice;
            String wholesalePrice;
            String minPrice;
            String referBuyPrice;
            boolean base;

            if (i==0){
                //基本单位
                base = true;
                unitName = getByMethodName("getUnit",excelGoods);
                times = "1";
                code = getByMethodName("getCode",excelGoods);
                retailPrice = getByMethodName("getRetailPrice",excelGoods);
                wholesalePrice = getByMethodName("getWholesalePrice",excelGoods);
                minPrice = getByMethodName("getMinPrice",excelGoods);
                referBuyPrice = getByMethodName("getReferBuyPrice",excelGoods);
            } else {
                base = false;
                unitName = getByMethodName("getUnit" + i,excelGoods);
                times = getByMethodName("getTimes" + i,excelGoods);
                code = getByMethodName("getCode" + i,excelGoods);
                retailPrice = getByMethodName("getRetailPrice" + i,excelGoods);
                wholesalePrice = getByMethodName("getWholesalePrice" + i,excelGoods);
                minPrice = getByMethodName("getMinPrice" + i,excelGoods);
                referBuyPrice = getByMethodName("getReferBuyPrice" + i,excelGoods);
            }

            //单位为空，则舍弃该单位
            if (Utils.isEmpty(unitName)) {
               // Logger.getLogger(ExcelGoodsListener.class).info("单位"+i+"为空,舍弃该单位");
                continue;
            }

            if (!Utils.isLetterDigit(code)) {
               // Logger.getLogger(ExcelGoodsListener.class).info("条码"+i+"【"+code+"】不是数字字母,舍弃该单位");
                continue;
            }

            //该商品已经插入过此单位，则取消该单位
            if (unitMap.containsKey(unitName)){
               // Logger.getLogger(ExcelGoodsListener.class).info("该商品已经插入过此单位【"+unitName+"】,舍弃该单位");
                continue;
            }

            //条码重复则跳过该商品
            if (sysCodeMap.containsKey(code)) {
               // Logger.getLogger(ExcelGoodsListener.class).info("条码【"+code+"】重复,舍弃该单位");
                continue;
            }

            GoodsUnit goodsUnit = new GoodsUnit();
            DataUtil.processEntity(company, goodsUnit,map);
            goodsUnit.setBase(base);
            goodsUnit.setTimes(new BigDecimal(times));

            if (sysUnitMap.containsKey(unitName)) {
                goodsUnit.setUnitId(sysUnitMap.get(unitName));
            } else {
                //系统中不存在，则生成一个单位
                Unit unit = genUnit(unitName);
                unitList.add(unit);
                goodsUnit.setUnitId(unit.getId());
                //将新生成的unit添加到
                sysUnitMap.put(unit.getName(),unit.getId());
            }

            goodsUnit.setCode(code);

            goodsUnit.setRetailPrice(new BigDecimal(retailPrice));
            goodsUnit.setWholesalePrice(new BigDecimal(wholesalePrice));
            goodsUnit.setMinPrice(new BigDecimal(minPrice));
            goodsUnit.setReferBuyPrice(new BigDecimal(referBuyPrice));
            goodsUnitList.add(goodsUnit);


            unitMap.put(unitName,"");//向临时map里添加已保存的unitname
            sysCodeMap.put(goodsUnit.getCode(), "");//向已添加列表里面添加已保存的code
        }

    }

    private String getStrNumber(String value){
        if (Utils.isNumber(value)) {
            return value;
        } else {
            return "0";
        }
    }

    private int getIntNumber(String value){
        if (Utils.isNumber(value)) {
            //先转成小数然后强转成整数，这样就会防止表格里面填写的是小数。而去除小数部分
            int iVal = (int) Float.parseFloat(value);
            //如果是负数，则转成正数
            if (iVal < 0) {
                iVal = -iVal;
            }
            return iVal;
        } else {
            return 0;
        }
    }

    private String getByMethodName(String methodName,ExcelGoods excelGoods){
        Class clazz = excelGoods.getClass();
        String value = "";
        try {
            Method method = clazz.getDeclaredMethod(methodName);
            value = (String) method.invoke(excelGoods);
        } catch (Exception e) {
        }
        if (!Utils.isEmpty(value)) {
            value = value.trim();
        }
        return value;
    }

    private void setAttr(int index, ExcelGoods excelGoods, Map<String,Object> map){
        String attrValue = getByMethodName("attr"+index, excelGoods);
        if (!Utils.isEmpty(attrValue)) {
            GoodsAttr goodsAttr = new GoodsAttr();
            DataUtil.processEntity(company, goodsAttr, map);

            if (sysAttrMap.containsKey(attrValue)) {
                goodsAttr.setAttrId(sysAttrMap.get(attrValue));
            } else {
                //若不存在，则需要添加属性
                Attr attr = genAttr(attrValue,index);
                attrList.add(attr);
                goodsAttr.setAttrId(attr.getId());
                //将新城村的type添加到map
                sysAttrMap.put(attrValue, attr.getId());
            }

            goodsAttrList.add(goodsAttr);
        }
    }



    private Unit genUnit(String name){
        Unit unit = new Unit();
        DataUtil.processEntity(company,unit);
        unit.setStatus(1);
        unit.setName(name);
        unit.setPoint(false);
        return unit;
    }

    private Attr genAttr(String attrValue, int index){
        Attr attr = new Attr();
        DataUtil.processEntity(company,attr);
        attr.setAttrValue(attrValue);
        attr.setAttrNameId(sysAttrNameMap.get(index));
        return attr;
    }
    private String getNo(){
        StringBuilder sb = new StringBuilder();
        sb.append(orderRule.getPrefix());
        sb.append(YYYYMMDD);
        sb.append(String.format("%0"+orderRule.getNum()+"d",orderRule.getCurrent()));
        orderRule.setCurrent(orderRule.getCurrent()+1);
        return sb.toString();
    }

    public List<Type> getTypeList() {
        return typeList;
    }

    public List<Unit> getUnitList() {
        return unitList;
    }

    public List<Attr> getAttrList() {
        return attrList;
    }

    public List<Goods> getGoodsList() {
        return goodsList;
    }

    public List<GoodsAttr> getGoodsAttrList() {
        return goodsAttrList;
    }

    public List<GoodsUnit> getGoodsUnitList() {
        return goodsUnitList;
    }

    public List<GoodsHouseWarn> getGoodsHouseWarnList() {
        return goodsHouseWarnList;
    }

    public List<DataMsg> getGoodsMsgList() {
        return goodsMsgList;
    }
}
